package com.punai.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.punai.common.annotation.DataScope;
import com.punai.common.constant.CompanyConstants;
import com.punai.common.constant.SysConstants;
import com.punai.common.constant.UserConstants;
import com.punai.common.constant.VerifyAccountConstants;
import com.punai.common.core.domain.entity.SysCompany;
import com.punai.common.core.domain.entity.SysDept;
import com.punai.common.core.domain.entity.SysRole;
import com.punai.common.core.domain.entity.SysUser;
import com.punai.common.core.text.Convert;
import com.punai.common.exception.ServiceException;
import com.punai.common.utils.SecurityUtils;
import com.punai.common.utils.StringUtils;
import com.punai.common.utils.spring.SpringUtils;
import com.punai.system.domain.SysCompanyRole;
import com.punai.system.domain.SysUserRole;
import com.punai.system.mapper.*;
import com.punai.system.service.ISysCompanyService;
import org.apache.commons.collections4.ListValuedMap;
import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SysCompanyServiceImpl implements ISysCompanyService {

    @Autowired
    private SysCompanyMapper sysCompanyMapper;
    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysUserRoleMapper userRoleMapper;
    @Autowired
    private SysCompanyRoleMapper sysCompanyRoleMapper;

    @Override
    public List<SysCompany> selectCompanyList(SysCompany company) {
        company.setCompanyId(SecurityUtils.getCompanyId());
        return sysCompanyMapper.selectCompanyList(company);
    }

    @Override
    public void checkCompanyDataScope(Long id) {
        if (!SysUser.isAdmin(SecurityUtils.getUserId()))
        {
            SysCompany company = new SysCompany();
            company.setId(id);
            List<SysCompany> companyList = SpringUtils.getAopProxy(this).selectCompanyList(company);
            if (StringUtils.isEmpty(companyList))
            {
                throw new ServiceException("没有权限访问企业数据！");
            }
        }
    }

    @Override
    public SysCompany selectCompanyById(Long id) {
        SysCompany sysCompany = sysCompanyMapper.selectCompanyById(id);
        Long companyId = sysCompany.getId();
        Long companyRoleIds = getCompanyRoleIds(companyId);
        sysCompany.setRoleId(companyRoleIds);
        return sysCompany;
    }

    private Long getCompanyRoleIds(Long companyId) {
        LambdaQueryWrapper<SysCompanyRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysCompanyRole::getCompanyId, companyId);
        SysCompanyRole companyRoles = sysCompanyRoleMapper.selectOne(queryWrapper);
        if (companyRoles != null) {
           return companyRoles.getRoleId();
        }
        return -1L;
    }

    @Override
    public String checkCompanyNameUnique(SysCompany company) {
        Long id = StringUtils.isNull(company.getId()) ? -1L : company.getId();
        String companyName = company.getCompanyName();
        LambdaQueryWrapper<SysCompany> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysCompany::getCompanyName,companyName);
        SysCompany sysCompany = sysCompanyMapper.selectOne(queryWrapper);
        if (ObjectUtil.isNotNull(sysCompany) && !sysCompany.getId().equals(id)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    public String checkCompanyPrxUnique(SysCompany company) {
        String prx = company.getPrx();
        LambdaQueryWrapper<SysCompany> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysCompany::getPrx,prx);
        Long count = sysCompanyMapper.selectCount(queryWrapper);
        if (count > 0) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    @Transactional
    public int insertCompany(SysCompany company) {
        Long userId = SecurityUtils.getUserId();
        boolean admin = SecurityUtils.isAdmin(userId);
        Long pid = company.getPid();
        if (pid == null && admin) {
            pid = CompanyConstants.DEF_TOP_COMPANY_ID;
        } else if (pid == null){
            throw new ServiceException("未选择父级公司");
        } else if (pid == CompanyConstants.DEF_TOP_COMPANY_PID && !admin) {
            throw new ServiceException("不允许新增顶级公司");
        }
        SysCompany info = sysCompanyMapper.selectCompanyById(pid);
        if (info == null && pid.equals(CompanyConstants.DEF_TOP_COMPANY_ID)) {
            info = new SysCompany();
            info.setPids(CompanyConstants.DEF_TOP_COMPANY_PID + "");
            info.setPid(CompanyConstants.DEF_TOP_COMPANY_ID);
        }
        if (info == null) {
            throw new ServiceException("未选择父级公司");
        }
        // 如果父节点不为正常状态,则不允许新增子节点
        if (!CompanyConstants.COMPANY_NORMAL.equals(info.getStatus()))
        {
            throw new ServiceException("公司停用，不允许新增");
        }
        company.setSource(admin ? SysConstants.DEFAULT_CREATE_TYPE : SysConstants.CREATE_TYPE);
        company.setStatus(CompanyConstants.COMPANY_NORMAL);
        company.setDelFlag("0");
        company.setPids(info.getPids() + "," + info.getId());
        company.setPid(pid);
        int insert = sysCompanyMapper.insert(company);
        initCompanyUserDeptData(company,userId);
        return insert;
    }

    /**
     * 初始化 创建公司附带数据
     * @param company
     * @param userId
     */
    private void initCompanyUserDeptData(SysCompany company,  Long userId) {

        Long companyId = company.getId();
        // 创建默认部门
        // 公司与部门的联系
        // 创建默认用户
        SysUser user = new SysUser();
        user.setUserName(company.getPrx() + "-0001");
        user.setNickName(company.getPrx() + "-管理员");
        String randomSalt = SecurityUtils.getRandomSalt();
        user.setSalt(randomSalt);
        user.setPassword(SecurityUtils.md5EncodePassword(company.getPrx() + "-0001" + randomSalt));
        user.setStatus("0");
        user.setDelFlag("0");
        user.setType(VerifyAccountConstants.ACCOUNT_TYPE.ZS.getCode());
        user.setUsePlace(VerifyAccountConstants.ACCOUNT_PLACE.PT.getCode());
        user.setCreateBy(userId + "");
        user.setCreateTime(new Date());
        user.setCompanyId(companyId);
        sysUserMapper.insert(user);

        /** 创建角色表 */
        Long roleId = company.getRoleId();
        /* 用户与角色 */
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(user.getUserId());
        sysUserRole.setRoleId(roleId);
        userRoleMapper.insert(sysUserRole);
        sysCompanyRoleMapper.insert(new SysCompanyRole(companyId,roleId));
    }

    @Override
    public int selectNormalChildrenCompanyById(Long id) {
        return sysCompanyMapper.selectNormalChildrenCompanyById(id);
    }

    @Override
    public int updateCompany(SysCompany company) {
        SysCompany newParentCompany = sysCompanyMapper.selectCompanyById(company.getPid());
        SysCompany oldCompany = sysCompanyMapper.selectCompanyById(company.getId());
        Long companyRoleIds = getCompanyRoleIds(company.getId());
        if (StringUtils.isNotNull(newParentCompany) && StringUtils.isNotNull(oldCompany))
        {
            String newAncestors = newParentCompany.getPids() + "," + newParentCompany.getId();
            String oldAncestors = oldCompany.getPids();
            company.setPids(newAncestors);
            updateCompanyChildren(company.getId(), newAncestors, oldAncestors);
        }
        int result = sysCompanyMapper.updateById(company);
        if (UserConstants.DEPT_NORMAL.equals(company.getStatus()) && StringUtils.isNotEmpty(company.getPids())
                && !StringUtils.equals("0", company.getPids()))
        {
            // 如果该公司是启用状态，则启用该公司的所有上级公司
            updateParentCompanyStatusNormal(company);
        }
        // 要删除的
        //oldRoleIds
        // 修复的   fixme
        // 新的     todo
        return result;
    }

    private void updateParentCompanyStatusNormal(SysCompany company) {
        String pids = company.getPids();
        Long[] companyIds = Convert.toLongArray(pids);
        sysCompanyMapper.updateCompanyStatusNormal(companyIds);
    }

    private void updateCompanyChildren(Long id, String newPids, String oldPids) {
        List<SysCompany> children = sysCompanyMapper.selectChildrenCompanyById(id);
        for (SysCompany child : children)
        {
            child.setPids(child.getPids().replaceFirst(oldPids, newPids));
        }
        if (children.size() > 0)
        {
            sysCompanyMapper.updateCompanyChildren(children);
        }
    }

    @Override
    public boolean hasChildByCompanyId(Long id) {
        int result = sysCompanyMapper.hasChildByCompanyId(id);
        return result > 0;
    }

    @Override
    public boolean checkCompanyExistUser(Long id) {
        int result = sysCompanyMapper.checkCompanyExistUser(id);
        return result > 0;
    }

    @Override
    @Transactional
    public int deleteCompanyById(Long id) {
        sysDeptMapper.deleteByCompanyId(id);
        sysUserMapper.deleteByCompanyId(id);
        return sysCompanyMapper.deleteCompanyById(id);
    }

    @Override
    public SysCompany treeCompanyList() {
        Long companyId = SecurityUtils.getCompanyId();
        Long deptId = SecurityUtils.getDeptId();
        SysCompany sysCompany;
        if (deptId == null || SecurityUtils.isAdmin(SecurityUtils.getUserId())) {
            sysCompany = sysCompanyMapper.selectCompanyById(companyId);
            List<SysCompany> companies = sysCompanyMapper.selectChildrenCompanyById(companyId);
            ListValuedMap<Long,SysCompany> levelMap = new ArrayListValuedHashMap<>();
            for (SysCompany company : companies) {
                levelMap.put(company.getPid(),company);
            }
            setTreeChild(sysCompany,levelMap);
        } else {
            sysCompany = sysCompanyMapper.selectCompanyById(companyId);
        }
        return sysCompany;
    }

    private void setTreeChild(SysCompany company, ListValuedMap<Long, SysCompany> levelMap) {
        Long id = company.getId();
        List<SysCompany> companies = levelMap.get(id);
        if (CollUtil.isNotEmpty(companies)) {
            List<SysCompany> children = company.getChildren();
            children.addAll(companies);
            for (SysCompany sysCompany : companies) {
                setTreeChild(sysCompany,levelMap);
            }
        }
    }


}
